/**
 *  @file FileStream.h
 */
#ifndef _FILESTREAM_H_
#define _FILESTREAM_H_

#include "Stream.h"


namespace cppflib
{

class CFString;
namespace collections { class BinBuf; }

namespace io
{

/**
 *  A class to read/write file
 */
class _DLLAPI FileStream : public Stream
{

public:
   //! file open attribute
   typedef enum _fileattr
   {
      FA_READONLY,         ///< read file only
      FA_READ_DETECTENC,   ///< read and detect encoding
      FA_WRITE,            ///< write file
      FA_APPEND            ///< append file
   } fileattr_t;

   //! file read/write encoding
   typedef enum _fileencoding
   {
      ENC_NONE,
      ENC_UTF8,            ///< UTF-8
      ENC_UTF16LE,         ///< UTF-16 little endian
      ENC_UTF16BE          ///< UTF-16 big endian
   } fileencoding_t;

   //! new line type
   typedef enum _newlinetype
   {
      NL_LF,      ///< single line feed
      NL_CRLF,    ///< carriage return line feed
   } newlinetype_t;

private:
   ptrany_t fileHandle;    ///< file handle/pointer
   fileattr_t openAttr;    ///< open file attribute
   fileencoding_t inEnc;   ///< input encoding
   fileencoding_t outEnc;  ///< output encoding
   newlinetype_t nlType;   ///< newline type
   const u8_t *outNewLine; ///< output newline (may be UTF-16 or UTF-8)
   cppflib::collections::BinBuf *pBinBuf; ///< a temp binary buffer

   FileStream(void);
   void ReleaseBeforeThrowing();
   void WriteString(CFString &szStr, bool isEndWithNewline);

public:
   FileStream(pcwstr_t szFilePath, fileattr_t openAttr);
   virtual ~FileStream(void);
   virtual void Close();
   virtual void Flush();
   virtual int Read(collections::ArrayByte &buffer);
   virtual int Read(collections::ArrayByte &buffer, int offset, int count);
   virtual int Read();   
   virtual i64_t Seek(i64_t offset, seekorigin_t origin);
   virtual int Write(collections::ArrayByte &buffer);
   virtual int Write(collections::ArrayByte &buffer, int offset, int count);
   virtual bool Write(u8_t val);

   bool Lock(i64_t pos, i64_t length);
   bool Unlock(i64_t pos, i64_t length);
   bool ReadLine(CFString &szStr);
   void Write(CFString &szStr);
   void WriteLine(CFString &szStr);
   void WriteBOM();
   fileencoding_t GetInputEncoding();
   fileencoding_t GetOutputEncoding();
   void SetInputEncoding(fileencoding_t enc);
   void SetOutputEncoding(fileencoding_t enc);
   void SetOutputNewLine(newlinetype_t nlType);
   u64_t GetFileSize();
};

} // end of namespace io

} // end of namespace cppflib

#endif
